package dfxnftables

import (
	"context"
	"fmt"

	"github.com/google/nftables"
)

// NfChain 表示一个 nftables 链的结构体，用于创建、检查或删除链。
// 它继承了 NfMeta 的元信息，并包含了链的基本属性。
type NfChain struct {
	NfMeta
	ChainName string                // 链名称
	Type      nftables.ChainType    // 链类型，如 filter、route 等；若为空则表示普通链（not base chain）
	Hook      *nftables.ChainHook   // 钩子点，仅在构建 base chain 时有效
	Priority  int32                 // 链优先级，仅在构建 base chain 时有效
	Policy    *nftables.ChainPolicy // 默认策略，可选
}

// CreateChain 在指定连接中创建该链。
// 如果 Type 被设置，则会创建一个 base chain 并填充 Hook、Priority 和 Policy 字段。
// 参数：
//   - ctx: 上下文，可用于超时控制等
//   - c: 与 nftables 通信的连接对象
//
// 返回值：
//   - error: 操作过程中发生的错误
func (n *NfChain) CreateChain(ctx context.Context, c *nftables.Conn) error {
	if err := n.NfMeta.Validate(); err != nil {
		return err
	}
	ch := &nftables.Chain{
		Table: n.Table(),
		Name:  n.ChainName,
	}

	// 如果设置了 Type，即表示构建 base chain，需要补齐 Hook/Priority/Policy
	if n.Type != "" {
		ch.Type = n.Type
		hook := n.Hook
		priority := nftables.ChainPriority(n.Priority)
		ch.Hooknum = hook
		ch.Priority = &priority
		if n.Policy != nil {
			ch.Policy = n.Policy
		}
	}

	c.AddChain(ch)
	return c.Flush()
}

// CheckChain 检查当前链是否已存在于系统中。
// 参数：
//   - ctx: 上下文
//   - c: 与 nftables 通信的连接对象
//
// 返回值：
//   - bool: 若存在返回 true，否则 false
//   - error: 查询过程中的错误
func (n *NfChain) CheckChain(ctx context.Context, c *nftables.Conn) (bool, error) {
	if err := n.NfMeta.Validate(); err != nil {
		return false, err
	}
	fam := n.Family()
	chains, err := c.ListChains()
	if err != nil {
		return false, err
	}
	for _, ch := range chains {
		if ch.Name == n.ChainName && ch.Table != nil && ch.Table.Name == n.TableName && ch.Table.Family == fam {
			return true, nil
		}
	}
	return false, nil
}

// DeleteChain 删除当前链（如果存在）。
// 参数：
//   - ctx: 上下文
//   - c: 与 nftables 通信的连接对象
//
// 返回值：
//   - []string: 当前实现始终返回空切片
//   - error: 删除操作失败时的错误
func (n *NfChain) DeleteChain(ctx context.Context, c *nftables.Conn) ([]string, error) {
	if err := n.NfMeta.Validate(); err != nil {
		return nil, err
	}
	fam := n.Family()
	chains, err := c.ListChains()
	if err != nil {
		return nil, err
	}
	for _, ch := range chains {
		if ch.Name == n.ChainName && ch.Table != nil && ch.Table.Name == n.TableName && ch.Table.Family == fam {
			c.DelChain(ch)
			if err := c.Flush(); err != nil {
				return nil, fmt.Errorf("flush after del chain failed: %w", err)
			}
			break
		}
	}
	return []string{}, nil
}

func (c *NfChain) QueryChainHandle(ctx context.Context, nftc *nftables.Conn, nft *nftables.Table) (*nftables.Chain, error) {
	return nftc.ListChain(nft, c.ChainName)
}
